#ifndef SRC_BASE_THREAD_H
#define SRC_BASE_THREAD_H

#include "base/macro_def.h"
#include "base/closure.h"
#include "base/scoped_ptr.h"

class Thread {
  public:
    explicit Thread(Closure* c)
        : closure_(c), tid_(-1) {
    }

    virtual ~Thread() {
      Join();
    }

    bool Start() {
      if (tid_ != -1) return true;

      int ret = ::pthread_create(&tid_, NULL, Thread::Run, closure_.get());
      if (ret == -1) {
        PLOG(WARNING)<< "pthread_create error";
        return false;
      }
      return true;
    }

    bool IsStart() const {
      return tid_ != -1;
    }

    virtual void Join() {
      if (tid_ == -1) return;
      int ret = ::pthread_join(tid_, NULL);
      PCHECK(ret != -1) << "pthread_join error";
      tid_ = -1;
    }

  private:
    pthread_t tid_;
    scoped_ptr<Closure> closure_;

    static void* Run(void* arg) {
      Closure* closure = (Closure*) arg;
      closure->Run();
      return NULL;
    }
};

class StopableThread : public Thread {
  public:
    explicit StopableThread(Closure* c)
        : Thread(closure_ = new StopableClosure(c)) {
    }

    virtual ~StopableThread() {
      Join();
    }

    void Join() {
      closure_->Stop();
      Thread::Join();
    }

  private:
    StopableClosure* closure_;

    DISALLOW_COPY_AND_ASSIGN(StopableThread);
};

#endif  // SRC_BASE_THREAD_H
